package e.odbo.data.generate.db;

import e.odbo.data.generate.GenerateConfig;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.platform.DatabaseNamesConstants;
import org.jumpmind.db.platform.DdlBuilderFactory;
import org.jumpmind.db.platform.IDatabasePlatform;
import org.jumpmind.db.platform.IDdlBuilder;
import org.jumpmind.db.sql.LogSqlResultsListener;
import org.jumpmind.db.sql.SqlScript;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;

public class DBGenerator {

    protected static final Logger log = LoggerFactory.getLogger(DBGenerator.class);

    String sampleDatabaseName = DatabaseNamesConstants.MYSQL;

    ArrayList<AbstractDBSchemaInterrupt> interrupts = new ArrayList<>();

    GenerateConfig config;

    protected IDatabasePlatform configDatabasePlatform;

    public DBGenerator(GenerateConfig config) {
        this.config = config;
        //this.configDatabasePlatform=configDatabasePlatform;
    }

    public void addInterrupts(AbstractDBSchemaInterrupt interrupt) {
        this.interrupts.add(interrupt);
    }

    public static String generateDataBaseSQL(Database database, String databasePlatformName, boolean dropTableFirst) {
        IDdlBuilder builder = DdlBuilderFactory.createDdlBuilder(databasePlatformName);
        return builder.createTables(database, dropTableFirst);
    }

    public String generateDataBaseSQLForVersion(Database v1, Database v2) {
        IDdlBuilder builder = configDatabasePlatform.getDdlBuilder();
        String alterSql = builder.alterDatabase(v1, v2);
        return alterSql;
    }

    public Database generateDatabaseForDB() {
        return generateDatabaseForDB(null, null, null);
    }

    public Database generateDatabaseForDB(String catalog, String schema, String[] tableTypes) {
        return configDatabasePlatform.readDatabase(catalog, schema, tableTypes);
    }

    public void generateDBSchema(Database database, boolean dropTablesFirst, boolean continueOnError) {
        configDatabasePlatform.createDatabase(database, dropTablesFirst, continueOnError);
    }

    //copy form ConfigDatabaseUpgrader
    public boolean updateDBSchema(Database database, String tablePrefix, boolean logOutput) {
        try {
            if (logOutput) {
                log.info("Checking if config tables need created or altered");
            }

            configDatabasePlatform.prefixDatabase(tablePrefix, database);
            Database modelFromDatabase = configDatabasePlatform.readFromDatabase(database.getTables());

            IDdlBuilder builder = configDatabasePlatform.getDdlBuilder();
            if (builder.isAlterDatabase(modelFromDatabase, database)) {
                if (logOutput) {
                    log.info("There are config tables that needed altered");
                }
                String delimiter = configDatabasePlatform.getDatabaseInfo()
                        .getSqlCommandDelimiter();

                String alterSql = builder.alterDatabase(modelFromDatabase, database);

                log.debug("Alter SQL generated: {}", alterSql);

                SqlScript script = new SqlScript(alterSql, configDatabasePlatform.getSqlTemplate(),
                        true, false, false, delimiter, null);
                if (logOutput) {
                    script.setListener(new LogSqlResultsListener(log));
                }
                script.execute(configDatabasePlatform.getDatabaseInfo()
                        .isRequiresAutoCommitForDdl());

                if (logOutput) {
                    log.info("Done with auto update of config tables");
                }
                return true;
            } else {
                return false;
            }
        } catch (RuntimeException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

    }

    public IDatabasePlatform getConfigDatabasePlatform() {
        return configDatabasePlatform;
    }

    public void setConfigDatabasePlatform(IDatabasePlatform configDatabasePlatform) {
        this.configDatabasePlatform = configDatabasePlatform;
    }
}
